package cn.android666.nopreviewcamera

import android.graphics.*
import org.opencv.android.Utils
import org.opencv.core.*
import org.opencv.imgproc.Imgproc
import timber.log.Timber
import androidx.core.graphics.createBitmap
import androidx.core.graphics.toColorInt

/**
 * 注，效率不高，比如生成一个时间水印，叠加到1080P上各步骤用时如下：
 * nv21ToRgb:36ms
 * createBitmap:1ms
 * addWater:0ms
 * rgbToYuv:39ms, total: 82ms
 * 生成水印和叠加水印这两步都挺快的，问题在于yuv转rgb和rgb转yuv这两步消耗时间太多了
 * 复用了代码中能复用的对象后，对于1080P还是很耗时，如下：
 * nv21ToRgb:18ms
 * createBitmap:2ms
 * addWater:1ms
 * rgbToYuv:39ms, total: 60ms
 *
 * 使用LibYuv库，把NV21转RGB（不是RGBA），对于一帧1080P的YUV也需要15ms，看OpenCV加水印的方案还是不行啊，因为它需要先把YUV转换为RGB，光这个转换就非常耗时了。
 */
object YUVWatermarkUtils {

    private var videoWidth = 0
    private var videoHeight = 0
    private lateinit var yuvMat: Mat
    private lateinit var rgbMat: Mat
    private lateinit var bitmapMat: Mat
    private lateinit var mask: Mat
    private lateinit var yuvI420: Mat
    private lateinit var i420Data: ByteArray
    private lateinit var nv21: ByteArray
    private var ySize: Int = 0
    private var uSize: Int = 0

    fun init(videoWidth: Int, videoHeight: Int) {
        this.videoWidth = videoWidth
        this.videoHeight = videoHeight
        yuvMat = Mat(videoHeight + videoHeight / 2, videoWidth, CvType.CV_8UC1)
        rgbMat = Mat()
        bitmapMat = Mat()
        mask = Mat()
        yuvI420 = Mat()

        ySize = videoWidth * videoHeight
        uSize = ySize / 4
        val totalSize = ySize + uSize * 2
        i420Data = ByteArray(totalSize)
        nv21 = ByteArray(totalSize)
    }

    fun addWatermarkToNV21(nv21: ByteArray, text: String, posX: Int = 20, posY: Int = 20): ByteArray {
        val ss = System.currentTimeMillis()
        // 1. NV21 → RGBA Mat
        var start = System.currentTimeMillis()
        val rgbMat = nv21ToRgbMat(nv21)
        Timber.i("nv21ToRgb:${System.currentTimeMillis() - start}ms")

        //Libyuv.NV21ToRGB(nv21, srcRGB, videoWidth, videoHeight)
        //Timber.i("nv21ToRgb:${System.currentTimeMillis() - start}ms")
        //start = System.currentTimeMillis()
        //rgbMat.put(0, 0, srcRGB)
        //Libyuv.fillBytesToMat(nv21, rgbMat)
        //Timber.i("grbToMat:${System.currentTimeMillis() - start}ms")

        // 2. 生成带描边的文字 Bitmap
        start = System.currentTimeMillis()
        val bitmap = WatermarkProducer.createTextBitmap(text, Bitmap.Config.RGB_565)
        Timber.i("createBitmap:${System.currentTimeMillis() - start}ms")

        // 3. Bitmap → Mat
        start = System.currentTimeMillis()
        val watermarkMat = bitmapToMat(bitmap)
        Timber.i("bitmapToMat:${System.currentTimeMillis() - start}ms")


        val copy1 = rgbMat.clone()
        val copy2 = watermarkMat.clone()

        // 4. 叠加水印到 RGBA Mat
        start = System.currentTimeMillis()
//        overlayWatermark(rgbMat, watermarkMat, posX, posY)
        overlayWatermark(copy1, copy2, posX, posY)
        Timber.i("addWater:${System.currentTimeMillis() - start}ms")

        // 5. RGBA Mat → NV21
        start = System.currentTimeMillis()
        //val nv21Bytes = rgbMatToNv21(rgbMat)
        val nv21Bytes = rgbMatToNv21(copy1)
        Timber.i("rgbToYuv:${System.currentTimeMillis() - start}ms, total: ${System.currentTimeMillis() - ss}ms")
        return nv21Bytes
    }




    private fun nv21ToRgbMat(nv21: ByteArray): Mat {
        yuvMat.put(0, 0, nv21)
        Imgproc.cvtColor(yuvMat, rgbMat, Imgproc.COLOR_YUV2RGB_NV21)
        return rgbMat
    }

    private fun rgbMatToNv21(rgb: Mat): ByteArray {
        Imgproc.cvtColor(rgb, yuvI420, Imgproc.COLOR_RGB2YUV_I420)
        yuvI420.get(0, 0, i420Data)

        // 复制 Y
        System.arraycopy(i420Data, 0, nv21, 0, ySize)

        // I420 = Y + U + V；NV21 = Y + VU
        for (i in 0 until uSize) {
            nv21[ySize + i * 2] = i420Data[ySize + uSize + i]       // V
            nv21[ySize + i * 2 + 1] = i420Data[ySize + i]           // U
        }
        return nv21
    }

    private fun bitmapToMat(bitmap: Bitmap): Mat {
        Utils.bitmapToMat(bitmap, bitmapMat)
        // 虽然Bitmap是RGB565，但是bitmapToMat返回的Mat是RGBA，所以需要转换为RGB
        Imgproc.cvtColor(bitmapMat, bitmapMat, Imgproc.COLOR_RGBA2RGB)
        return bitmapMat
    }

    /*fun overlayWatermark(rgbaMat: Mat, watermarkMat: Mat, posX: Int, posY: Int) {
        // 将水印叠加到指定位置
        val roi = rgbaMat.submat(posY, posY + watermarkMat.rows(), posX, posX + watermarkMat.cols())
        watermarkMat.copyTo(roi)
    }*/

    fun overlayWatermark(rgbaMat: Mat, watermarkMat: Mat, posX: Int, posY: Int) {
        // 1. 创建掩膜：识别纯蓝色背景（R=0, G=0, B=255）
        val channels = ArrayList<Mat>()
        Core.split(watermarkMat, channels) // 分离RGB三通道

        // 定义纯蓝色阈值（允许轻微偏差）
        val maskR = Mat() // 红色通道掩膜（R≤10）
        val maskG = Mat() // 绿色通道掩膜（G≤10）
        val maskB = Mat() // 蓝色通道掩膜（B≥245）

        Core.compare(channels[0], Scalar(10.0), maskR, Core.CMP_LE)  // R <= 10
        Core.compare(channels[1], Scalar(10.0), maskG, Core.CMP_LE)  // G <= 10
        Core.compare(channels[2], Scalar(245.0), maskB, Core.CMP_GE) // B >= 245

        // 合并条件（R、G均≤10且B≥245）
        val mask = Mat()
        Core.bitwise_and(maskR, maskG, mask)
        Core.bitwise_and(mask, maskB, mask)

        // 2. 反相掩膜（使非背景区域为255）
        Core.bitwise_not(mask, mask)

        // 3. 带掩膜的叠加
        val roi = rgbaMat.submat(posY, posY + watermarkMat.rows(), posX, posX + watermarkMat.cols())
        watermarkMat.copyTo(roi, mask)

        // 释放临时Mat对象
        channels.forEach { it.release() }
        maskR.release(); maskG.release(); maskB.release(); mask.release()
    }

 /*   fun overlayWatermark(rgbaMat: Mat, watermarkMat: Mat, posX: Int, posY: Int) {
        // 1. 创建掩膜：识别蓝色背景
        val hsvMat = Mat()
        val mask = Mat()
        Imgproc.cvtColor(watermarkMat, hsvMat, Imgproc.COLOR_RGB2HSV) // RGB转HSV更易识别颜色

        // 定义蓝色范围（HSV空间）
        val lowerBlue = Scalar(100.0, 150.0, 50.0)  // H:100~130对应蓝色
        val upperBlue = Scalar(130.0, 255.0, 255.0)
        Core.inRange(hsvMat, lowerBlue, upperBlue, mask) // 生成掩膜

        // 2. 反相掩膜（使非背景区域为255）
        Core.bitwise_not(mask, mask)

        // 3. 带掩膜的叠加
        val roi = rgbaMat.submat(posY, posY + watermarkMat.rows(), posX, posX + watermarkMat.cols())
        watermarkMat.copyTo(roi, mask)

        // 释放临时Mat对象
        hsvMat.release()
        mask.release()
    }*/


}